<?php

// +----------------------------------------------------------------------
// | Plugin for ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2021 青海云音信息技术有限公司 [ http://www.yyinfos.com ]
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | gitee 代码仓库：https://gitee.com/qhweb/ThinkAdmin
// +----------------------------------------------------------------------


namespace qhweb\service;

use think\admin\Service;
use think\admin\Library;
use think\admin\Exception;
use think\admin\helper\FormHelper;
use think\admin\helper\SaveHelper;
use think\admin\helper\QueryHelper;
use think\admin\helper\DeleteHelper;
use think\admin\service\SystemService;
use think\admin\extend\VirtualModel;
use think\Container;
use think\exception\HttpResponseException;
/**
 * 数据操作服务管理
 * @class ModelService
 * @package qhweb\service
 */
class ModelService extends Service
{
    /**
     * 静态初始化对象
     * @param string $name
     * @param array $args
     * @return mixed
     * @throws \think\admin\Exception
     */
    public static function __callStatic(string $name, array $args)
    {
        $hooks = [
            'mForm'   => [FormHelper::class, 'init'],
            'mSave'   => [SaveHelper::class, 'init'],
            'mQuery'  => [QueryHelper::class, 'init'],
            'mDelete' => [DeleteHelper::class, 'init'],
            'mUpdate' => [SystemService::class, 'save'],
        ];
        
        [$type, $base, $method, $model] = static::parseName($name);
        // halt($type, $base, $method, $model);
        if ("{$type}{$base}" !== $name) {
            throw new Exception("抱歉，实例 {$name} 不符合规则！");
        }
        // halt($model instanceof \think\Model);
        if (class_exists($model) || $model instanceof \think\Model) {
            if($method){
                try {
                    $action = 'm'.$method;
                    if (isset($hooks[$action])) {
                        [$class, $method] = $hooks[$action];
                        return Container::getInstance()->invokeClass($class)->$method($model, ...$args);
                    } else {
                        return Container::getInstance()->invokeClass($model)->$action(...$args);
                    }
                } catch (HttpResponseException $e) {
                    throw $e;
                } catch (\Exception $e) {
                    throw new Exception($e->getMessage());
                }
            }else{
                if($model instanceof \think\Model){
                    return $model;
                }
                return Container::getInstance()->invokeClass($model, ...$args);
            }
        } else {
            throw new Exception("抱歉，接口模式无法实例 {$model} 对象！");
        }
    }

    /**
     * 解析调用方法名称
     * @param string $name
     * @return array
     */
    private static function parseMethod(string $name): array
    {
        foreach (['Save', 'Update', 'Insert', 'Delete','List','Query','Form','Pagelist'] as $method) {
            if (strpos($name, $method) > 0) {
                [$base, ] = explode($method, $name);
                return [$base, $method];
            }
        }
        return [$name,''];
    }

    /**
     * 所有模块名称
     * @param string $name
     * @return array
     */
    private static function parseModule(): array
    {
        $appPath = Library::$sapp->getBasePath();
        $modules = ['Think','System'];
        foreach (scandir($appPath) as $file) {
            if($file !='.' && $file != '..' && is_dir($appPath.$file)){
                array_push($modules,ucfirst($file));
            }
        }
        return $modules;
    }

    /**
     * 解析调用对象名称
     * @param string $name
     * @return array
     */
    private static function parseName(string $name): array
    {
        foreach (self::parseModule() as $type) {
            if (strpos($name, $type) === 0) {
                [, $base] = explode($type, $name);
                [$model, $method] = static::parseMethod($base);
                if(strtolower($type) == 'think'){
                    $class = "\\qhweb\\model\\{$model}";
                    if(!class_exists($class)){
                        $class = VirtualModel::mk($model);
                    }
                }elseif(strtolower($type) == 'system'){
                    $class = "\\think\\admin\\model\\System{$model}";
                }else{
                    $class = "\\app\\{$type}\\model\\{$model}";
                }
                return [$type, $base, $method, $class];
            }
        }
        return ['-', '-', '',$name];
    }    
}
